#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__
#include "../mqcommon/mq_msg.pb.h"
#include "../mqcommon/mq_helper.hpp"

namespace csjmq
{
    class Router
    {
    public:
        // 判断routing_key是否合法
        static bool isLegalRoutingkey(const std::string &routing_key)
        {
            // routing_key只能包含这些字符（a~z, A~Z, 0~9, ., _）
            for (auto &ch : routing_key)
            {
                if (('a' <= ch && ch <= 'z') ||
                    ('A' <= ch && ch <= 'Z') ||
                    ('0' <= ch && ch <= '9') ||
                    ch == '.' || ch == '_')
                    continue;
                return false;
            }
            return true;
        }

        static bool isLegalBindingkey(const std::string &binding_key)
        {
            // routing_key只能包含这些字符（a~z, A~Z, 0~9, ., _, #, *）
            // 1.不能有不合法的字符
            for (auto &ch : binding_key)
            {
                if (('a' <= ch && ch <= 'z') ||
                    ('A' <= ch && ch <= 'Z') ||
                    ('0' <= ch && ch <= '9') ||
                    ch == '.' || ch == '_' ||
                    ch == '*' || ch == '#')
                    continue;
                return false;
            }

            // 2.*和#必须独立存在，在单词中不能出现，如root.pop*.for
            std::vector<std::string> sub_words;
            csjmq::StrHelper::split(binding_key, ".", sub_words);
            for (auto &word : sub_words)
            {
                if (word.size() > 1 && (word.find('*') != std::string::npos ||
                                        word.find('#') != std::string::npos))
                    return false;
            }

            // 3.*和#不能连续出现， #的两边不能是#/*
            for (int i = 1; i < sub_words.size(); i++)
            {
                if (sub_words[i - 1] == "*" && sub_words[i] == "#")
                    return false;
                if (sub_words[i - 1] == "#" && sub_words[i] == "#")
                    return false;
                if (sub_words[i - 1] == "#" && sub_words[i] == "*")
                    return false;
            }
            return true;
        }

        static bool route(ExchangeType type, const std::string &routing_key,
                          const std::string &binding_key)
        {
            if (type == ExchangeType::DIRECT)
                return (routing_key == binding_key);
            else if (type == ExchangeType::FANOUT)
                return true;

            std::vector<std::string> rkeys, bkeys;
            int n_rkey = StrHelper::split(routing_key, ".", rkeys);
            int n_bkey = StrHelper::split(binding_key, ".", bkeys);

            std::vector<std::vector<bool>> dp(n_bkey + 1, std::vector<bool>(n_rkey + 1, false));
            dp[0][0] = true;

            // 如果binding_key第一个单词不是通配符*，#，
            // 并且binding_key和routing_key的第一个单词就不相同的话就直接返回false
            if (bkeys[0] != "*" && bkeys[0] != "#" && (bkeys[0] != rkeys[0]))
                return false;

            // 如果bkeys起始就是#的话，那么当前列的行就要修改为true，为了下面的单词进行继承
            for (int i = 1; i <= n_bkey; i++)
            {
                if (bkeys[i - 1] != "#")
                    break;
                dp[i][0] = true;
            }

            for (int i = 1; i <= n_bkey; i++)
            {
                for (int j = 1; j <= n_rkey; j++)
                {
                    // 如果当前binding_key的单词为#的话，就要从左上角，左，上三个地方进行继承
                    if (bkeys[i - 1] == "#")
                        dp[i][j] = dp[i - 1][j - 1] | dp[i][j - 1] | dp[i - 1][j];
                    else if (bkeys[i - 1] == "*" || bkeys[i - 1] == rkeys[j - 1])
                    {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                }
            }
            return dp[n_bkey][n_rkey];
        }
    };

}
#endif
